package com.capinfo.commons.project.model.security;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

import com.capinfo.commons.project.model.region.Region;
import com.capinfo.components.security.model.SecureUser;

@Entity
@Table(name = "SYSTEM_USERS")
@SequenceGenerator(name = "seqAdminUser", sequenceName = "SEQ_USERS", allocationSize = 1)
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class SystemUser implements SecureUser<SystemUser, SystemRole>{
	private static final long serialVersionUID = 1L;

	//ID
	private Long id;
	
	//登录名
	private String logonName;
	
	//密码
	private String password = "";
	
	//姓名（昵称）
	private String name;
	
	//是否可用
	private Boolean enabled = Boolean.TRUE;

	//角色
	private Long[] roleIds = new Long[0];
	private Set<SystemRole> roles = new HashSet<SystemRole>();

	//区域
	private Long regionId = new Long(0);
	private Region region;

	public SystemUser() {
	}

	
	@Id
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seqAdminUser")
	@Column(name = "ID", unique = true, nullable = false, precision = 12, scale = 0)
	public java.lang.Long getId() {
		return this.id;
	}

	public void setId(java.lang.Long id) {
		this.id = id;
	}

	@Column(name = "USER_NAME", length = 50)
	public String getLogonName() {
		return logonName;
	}

	public void setLogonName(String logonName) {
		this.logonName = logonName;
	}

	@Column(name = "PASSWORD", length = 32)
	public String getPassword() {
		return this.password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	
	@Column(name = "NICK_NAME", length = 30)
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	@Column(name = "ENABLED", precision = 1, scale = 0)
	public java.lang.Boolean getEnabled() {
		return this.enabled;
	}

	public void setEnabled(java.lang.Boolean enabled) {
		this.enabled = enabled;
	}

	@Transient
	public Long[] getRoleIds() {

		if (0 == roleIds.length) {

			Set<SystemRole> roles = this.getRoles();
			roleIds = new Long[roles.size()];
			int i = 0;
			for (SystemRole role : roles) {
				roleIds[i] = role.getId();
				i++;
			}
		}

		return roleIds;
	}

	
	@Transient
	public String getRoleIdString() {

		StringBuilder roleIdStringBuilder = new StringBuilder();
		for(SystemRole role: roles) {
			
			roleIdStringBuilder.append("|*, ").append(role.getId()).append(", *");
		}
		String roleIdString = roleIdStringBuilder.toString();
		if( StringUtils.isNotBlank(roleIdString) ) {
			
			roleIdString = roleIdString.substring(1);
		}
		return roleIdString;
	}
	
	
	@ManyToMany(targetEntity = SystemRole.class, cascade = CascadeType.REFRESH, fetch = FetchType.LAZY)
	@JoinTable(name = "SYSTEM_USERS_ROLES", joinColumns = @JoinColumn(name = "USER_ID"), inverseJoinColumns = @JoinColumn(name = "ROLE_ID"))
	public Set<SystemRole> getRoles() {
		return roles;
	}

	public void setRoles(Set<SystemRole> roles) {
		this.roles = roles;
	}

	@Column(name = "REGION_ID")
	public Long getRegionId() {
		return regionId;
	}

	public void setRegionId(Long regionId) {
		this.regionId = regionId;
	}

	@ManyToOne(targetEntity = Region.class, cascade = CascadeType.REFRESH, fetch = FetchType.LAZY)
	@JoinColumn(name="REGION_ID", insertable=false, updatable=false)
	public Region getRegion() {
		
		return this.region;
	}
	
	public void setRegion(Region region) {
		
		this.region = region;
	}
	
	public String toString() {

		return new ToStringBuilder(this)
				.append("id", getId())
				.append("logonName", getLogonName())
				.append("name", getName())
				.append("roles", getRoles()).toString();
	}

	public boolean equals(Object other) {

		if ((this == other))
			return true;
		if (!(other instanceof SystemUser))
			return false;

		SystemUser castOther = (SystemUser) other;
		return new EqualsBuilder().append(this.getId(), castOther.getId())
				.append(this.getLogonName(), castOther.getLogonName())
				.append(this.getPassword(), castOther.getPassword())
				.append(this.getName(), castOther.getName()).isEquals();
	}

	public int hashCode() {

		return new HashCodeBuilder().append(getId()).append(getLogonName()).append(getName())
				.toHashCode();
	}
}